import Arc from './Arc'
import TreeNode from './TreeNode'
import { fillText } from '@/utils/common'
import Line from './Line'

export default class AvlTreeNode extends TreeNode {
  constructor(x, y, arcX, arcY, value, key, index, color) {
    super(x, y, arcX, arcY, value, key, index, color)
    this.height = 1
    this.heightTextColor = 'blue'
  }

  draw(ctx) {
    super.draw(ctx)
    this.drawHeightText(ctx)
  }

  drawHeightText(ctx) {
    ctx.beginPath()
    ctx.fillStyle = this.heightTextColor
    ctx.font = 'bold ' + (14 * window.devicePixelRatio) + 'px serif'
    fillText(ctx, this.height, this.x - Arc.R, this.y - Arc.R)
  }

  setHeightTextColor(color) {
    this.heightTextColor = color
  }

  balanceFactor() {
    let leftHeight = this.left ? this.left.height : 0
    let rightHeight = this.right ? this.right.height : 0
    return leftHeight - rightHeight
  }

  isBalanced() {
    return Math.abs(this.balanceFactor()) <= 1
  }

  updateHeight() {
    let leftHeight = this.left ? this.left.height : 0
    let rightHeight = this.right ? this.right.height : 0
    this.height = 1 + Math.max(leftHeight, rightHeight)
  }

  tallerChild() {
    let leftHeight = this.left ? this.left.height : 0
    let rightHeight = this.right ? this.right.height : 0
    if (leftHeight > rightHeight) {
      return this.left
    }
    if (leftHeight < rightHeight) {
      return this.right
    }
    return this.isLeftChild() ? this.left : this.right
  }

  isLeftChild() {
    return this.parent && this === this.parent.left
  }

  isRightChild() {
    return this.parent && this === this.parent.right
  }

  deepCopy() {
    let treeNode = new AvlTreeNode(this.x, this.y, this.arc.x, this.arc.y, this.value, this.key, this.arc.index, this.arc.color)
    treeNode.height = this.height
    let arc = treeNode.arc
    if (this.arc.left) {
      let { fromX, fromY, toX, toY } = this.arc.left
      arc.setLeft(new Line(fromX, fromY, toX, toY))
    }

    if (this.arc.right) {
      let { fromX, fromY, toX, toY } = this.arc.right
      arc.setRight(new Line(fromX, fromY, toX, toY))
    }

    return treeNode
  }
}